+++ /dev/null
-/*
- * Copyright (c) 2014 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <glib/gi18n-lib.h>
-
-#include "signals-list.h"
-
-#include "gtkcellrenderer.h"
-#include "gtkliststore.h"
-#include "gtktextbuffer.h"
-#include "gtktogglebutton.h"
-#include "gtktreeviewcolumn.h"
-#include "gtklabel.h"
-
-enum
-{
- COLUMN_NAME,
- COLUMN_CLASS,
- COLUMN_CONNECTED,
- COLUMN_COUNT,
- COLUMN_NO_HOOKS,
- COLUMN_SIGNAL_ID,
- COLUMN_HOOK_ID
-};
-
-enum
-{
- PROP_0,
- PROP_TRACE_BUTTON,
- PROP_CLEAR_BUTTON
-};
-
-struct _GtkInspectorSignalsListPrivate
-{
- GtkWidget *view;
- GtkListStore *model;
- GtkTextBuffer *text;
- GtkWidget *log_win;
- GtkWidget *trace_button;
- GtkWidget *clear_button;
- GtkTreeViewColumn *count_column;
- GtkCellRenderer *count_renderer;
- GObject *object;
- GHashTable *iters;
- gboolean tracing;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorSignalsList, gtk_inspector_signals_list, GTK_TYPE_PANED)
-
-static GType *
-get_types (GObject *object, guint *length)
-{
- GHashTable *seen;
- GType *ret;
- GType type;
- GType *iface;
- gint i;
-
- seen = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- type = ((GTypeInstance*)object)->g_class->g_type;
- while (type)
- {
- g_hash_table_add (seen, GSIZE_TO_POINTER (type));
- iface = g_type_interfaces (type, NULL);
- for (i = 0; iface[i]; i++)
- g_hash_table_add (seen, GSIZE_TO_POINTER (iface[i]));
- g_free (iface);
- type = g_type_parent (type);
- }
-
- ret = (GType *)g_hash_table_get_keys_as_array (seen, length);
- g_hash_table_unref (seen);
-
- return ret;
-}
-
-static void
-add_signals (GtkInspectorSignalsList *sl,
- GType type,
- GObject *object)
-{
- guint *ids;
- guint n_ids;
- gint i;
- GSignalQuery query;
- GtkTreeIter iter;
- gboolean has_handler;
-
- if (!G_TYPE_IS_INSTANTIATABLE (type) && !G_TYPE_IS_INTERFACE (type))
- return;
-
- ids = g_signal_list_ids (type, &n_ids);
- for (i = 0; i < n_ids; i++)
- {
- g_signal_query (ids[i], &query);
- has_handler = g_signal_has_handler_pending (object, ids[i], 0, TRUE);
- gtk_list_store_append (sl->priv->model, &iter);
- gtk_list_store_set (sl->priv->model, &iter,
- COLUMN_NAME, query.signal_name,
- COLUMN_CLASS, g_type_name (type),
- COLUMN_CONNECTED, has_handler ? _("Yes") : "",
- COLUMN_COUNT, 0,
- COLUMN_NO_HOOKS, (query.signal_flags & G_SIGNAL_NO_HOOKS) != 0,
- COLUMN_SIGNAL_ID, ids[i],
- COLUMN_HOOK_ID, 0,
- -1);
- g_hash_table_insert (sl->priv->iters,
- GINT_TO_POINTER (ids[i]), gtk_tree_iter_copy (&iter));
- }
- g_free (ids);
-}
-
-static void
-read_signals_from_object (GtkInspectorSignalsList *sl,
- GObject *object)
-{
- GType *types;
- guint length;
- gint i;
-
- types = get_types (object, &length);
- for (i = 0; i < length; i++)
- add_signals (sl, types[i], object);
- g_free (types);
-}
-
-static void stop_tracing (GtkInspectorSignalsList *sl);
-
-void
-gtk_inspector_signals_list_set_object (GtkInspectorSignalsList *sl,
- GObject *object)
-{
- if (sl->priv->object == object)
- return;
-
- stop_tracing (sl);
- gtk_list_store_clear (sl->priv->model);
- g_hash_table_remove_all (sl->priv->iters);
-
- sl->priv->object = object;
-
- if (object)
- read_signals_from_object (sl, object);
-}
-
-static void
-render_count (GtkTreeViewColumn *column,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- gint count;
- gboolean no_hooks;
- gchar text[100];
-
- gtk_tree_model_get (model, iter,
- COLUMN_COUNT, &count,
- COLUMN_NO_HOOKS, &no_hooks,
- -1);
- if (no_hooks)
- {
- g_object_set (renderer, "markup", "<i>(untraceable)</i>", NULL);
- }
- else if (count != 0)
- {
- g_snprintf (text, 100, "%d", count);
- g_object_set (renderer, "text", text, NULL);
- }
- else
- g_object_set (renderer, "text", "", NULL);
-}
-
-static void
-gtk_inspector_signals_list_init (GtkInspectorSignalsList *sl)
-{
- sl->priv = gtk_inspector_signals_list_get_instance_private (sl);
- gtk_widget_init_template (GTK_WIDGET (sl));
-
- gtk_tree_view_column_set_cell_data_func (sl->priv->count_column,
- sl->priv->count_renderer,
- render_count,
- NULL, NULL);
-
- sl->priv->iters = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- (GDestroyNotify) gtk_tree_iter_free);
-}
-
-static gboolean
-trace_hook (GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue *param_values,
- gpointer data)
-{
- GtkInspectorSignalsList *sl = data;
- GObject *object;
-
- object = g_value_get_object (param_values);
-
- if (object == sl->priv->object)
- {
- gint count;
- GtkTreeIter *iter;
-
- iter = (GtkTreeIter *)g_hash_table_lookup (sl->priv->iters, GINT_TO_POINTER (ihint->signal_id));
-
- gtk_tree_model_get (GTK_TREE_MODEL (sl->priv->model), iter, COLUMN_COUNT, &count, -1);
- gtk_list_store_set (sl->priv->model, iter, COLUMN_COUNT, count + 1, -1);
- }
-
- return TRUE;
-}
-
-static gboolean
-start_tracing_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- GtkInspectorSignalsList *sl = data;
- guint signal_id;
- gulong hook_id;
- gboolean no_hooks;
-
- gtk_tree_model_get (model, iter,
- COLUMN_SIGNAL_ID, &signal_id,
- COLUMN_HOOK_ID, &hook_id,
- COLUMN_NO_HOOKS, &no_hooks,
- -1);
-
- g_assert (signal_id != 0);
- g_assert (hook_id == 0);
-
- if (!no_hooks)
- {
- hook_id = g_signal_add_emission_hook (signal_id, 0, trace_hook, sl, NULL);
-
- gtk_list_store_set (GTK_LIST_STORE (model), iter,
- COLUMN_COUNT, 0,
- COLUMN_HOOK_ID, hook_id,
- -1);
- }
-
- return FALSE;
-}
-
-static gboolean
-stop_tracing_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- guint signal_id;
- gulong hook_id;
-
- gtk_tree_model_get (model, iter,
- COLUMN_SIGNAL_ID, &signal_id,
- COLUMN_HOOK_ID, &hook_id,
- -1);
-
- g_assert (signal_id != 0);
-
- if (hook_id != 0)
- {
- g_signal_remove_emission_hook (signal_id, hook_id);
- gtk_list_store_set (GTK_LIST_STORE (model), iter,
- COLUMN_HOOK_ID, 0,
- -1);
- }
-
- return FALSE;
-}
-
-static void
-start_tracing (GtkInspectorSignalsList *sl)
-{
- sl->priv->tracing = TRUE;
- gtk_tree_model_foreach (GTK_TREE_MODEL (sl->priv->model), start_tracing_cb, sl);
-}
-
-static void
-stop_tracing (GtkInspectorSignalsList *sl)
-{
- sl->priv->tracing = FALSE;
- gtk_tree_model_foreach (GTK_TREE_MODEL (sl->priv->model), stop_tracing_cb, sl);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sl->priv->trace_button), FALSE);
-}
-
-static void
-toggle_tracing (GtkToggleButton *button, GtkInspectorSignalsList *sl)
-{
- if (gtk_toggle_button_get_active (button) == sl->priv->tracing)
- return;
-
- //gtk_widget_show (sl->priv->log_win);
-
- if (gtk_toggle_button_get_active (button))
- start_tracing (sl);
- else
- stop_tracing (sl);
-}
-
-static gboolean
-clear_log_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- gtk_list_store_set (GTK_LIST_STORE (model), iter, COLUMN_COUNT, 0, -1);
- return FALSE;
-}
-
-static void
-clear_log (GtkButton *button, GtkInspectorSignalsList *sl)
-{
- gtk_text_buffer_set_text (sl->priv->text, "", -1);
-
- gtk_tree_model_foreach (GTK_TREE_MODEL (sl->priv->model), clear_log_cb, sl);
-}
-
-static void
-get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkInspectorSignalsList *sl = GTK_INSPECTOR_SIGNALS_LIST (object);
-
- switch (param_id)
- {
- case PROP_TRACE_BUTTON:
- g_value_take_object (value, sl->priv->trace_button);
- break;
-
- case PROP_CLEAR_BUTTON:
- g_value_take_object (value, sl->priv->trace_button);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkInspectorSignalsList *sl = GTK_INSPECTOR_SIGNALS_LIST (object);
-
- switch (param_id)
- {
- case PROP_TRACE_BUTTON:
- sl->priv->trace_button = g_value_get_object (value);
- break;
-
- case PROP_CLEAR_BUTTON:
- sl->priv->clear_button = g_value_get_object (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-constructed (GObject *object)
-{
- GtkInspectorSignalsList *sl = GTK_INSPECTOR_SIGNALS_LIST (object);
-
- g_signal_connect (sl->priv->trace_button, "toggled",
- G_CALLBACK (toggle_tracing), sl);
- g_signal_connect (sl->priv->clear_button, "clicked",
- G_CALLBACK (clear_log), sl);
-}
-
-static void
-gtk_inspector_signals_list_class_init (GtkInspectorSignalsListClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- object_class->constructed = constructed;
- object_class->get_property = get_property;
- object_class->set_property = set_property;
-
- g_object_class_install_property (object_class, PROP_TRACE_BUTTON,
- g_param_spec_object ("trace-button", NULL, NULL,
- GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class, PROP_CLEAR_BUTTON,
- g_param_spec_object ("clear-button", NULL, NULL,
- GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/signals-list.ui");
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, view);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, model);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, text);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, log_win);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, count_column);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, count_renderer);
-}
-
-// vim: set et sw=2 ts=2:
+++ /dev/null
-<interface domain="gtk40">
- <object class="GtkListStore" id="model">
- <columns>
- <column type="gchararray"/>
- <column type="gchararray"/>
- <column type="gchararray"/>
- <column type="gint"/>
- <column type="gboolean"/>
- <column type="guint"/>
- <column type="gulong"/>
- </columns>
- </object>
- <object class="GtkTextBuffer" id="text"/>
- <template class="GtkInspectorSignalsList" parent="GtkPaned">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkScrolledWindow">
- <property name="expand">1</property>
- <property name="hscrollbar-policy">never</property>
- <child>
- <object class="GtkTreeView" id="view">
- <property name="model">model</property>
- <property name="enable-search">0</property>
- <property name="enable-grid-lines">vertical</property>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">Signal</property>
- <property name="sort-column-id">0</property>
- <child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- </object>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">Connected</property>
- <child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- </object>
- <attributes>
- <attribute name="text">2</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn" id="count_column">
- <property name="title" translatable="yes">Count</property>
- <child>
- <object class="GtkCellRendererText" id="count_renderer">
- <property name="scale">0.8</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">Defined At</property>
- <property name="sort-column-id">1</property>
- <child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- </object>
- <attributes>
- <attribute name="text">1</attribute>
- </attributes>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="log_win">
- <property name="expand">1</property>
- <property name="vscrollbar-policy">always</property>
- <property name="shadow-type">in</property>
- <child>
- <object class="GtkTextView">
- <property name="buffer">text</property>
- <property name="editable">0</property>
- </object>
- </child>
- </object>
- </child>
- </template>
-</interface>